package com.nebula.salary.portal.controller.manage;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.errorprone.annotations.Var;
import com.nebula.salary.common.constants.Const;
import com.nebula.salary.common.constants.ReturnMessage;
import com.nebula.salary.common.exception.CustomException;
import com.nebula.salary.common.result.ServerResponse;
import com.nebula.salary.common.utils.JwtTokenUtil;
import com.nebula.salary.common.utils.RedisUtil;
import com.nebula.salary.common.utils.SecurityUtil;
import com.nebula.salary.model.dto.RoleDto;
import com.nebula.salary.model.dto.RoleQueryDto;
import com.nebula.salary.model.pojo.Navigation;
import com.nebula.salary.model.pojo.Role;
import com.nebula.salary.model.pojo.User;
import com.nebula.salary.model.vo.LoginUser;
import com.nebula.salary.model.vo.PageResult;
import com.nebula.salary.model.vo.RoleMenuVo;
import com.nebula.salary.model.vo.RoleVo;
import com.nebula.salary.portal.service.INavigationService;
import com.nebula.salary.portal.service.IRoleService;
import com.nebula.salary.portal.service.IUserService;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 角色表 前端控制器
 * </p>
 *
 * @author codex
 * @since 2022-01-24
 */
@RestController
@RequestMapping("/manage/role")
@Api(tags = "角色管理")
public class RoleController {
    
    @Resource
    private IRoleService roleService;
    
    @Resource
    private IUserService userService;
    
    @Resource
    private JwtTokenUtil jwtTokenUtil;
    
    @Resource
    private RedisUtil redisUtil;
    
    @Autowired
    private INavigationService navigationService;
    
    @ApiOperation(value = "根据角色ID获取菜单列表")
    @GetMapping("/roleMenuSelect/{roleId}")
    public ServerResponse<Map<String, Object>> roleMenuSelect(@ApiParam(value = "角色ID", required = true)
                                                              @PathVariable Integer roleId) {
        List<Navigation> navigations = navigationService.selectMenuListByUserId();
        Map<String, Object> map = new HashMap<>(2);
        map.put("checkedKeys", navigationService.selectMenuListByRoleId(roleId));
        map.put("menus", navigationService.buildMenuTreeSelect(navigations));
        
        return ServerResponse.createBySuccess(map);
    }
    
    
    @ApiOperation(value = "根据用户ID获取菜单树形列表")
    @GetMapping("/treeSelect")
    public ServerResponse<List<RoleMenuVo>> treeSelect() {
        List<Navigation> list = navigationService.treeSelect();
        return ServerResponse.createBySuccess(navigationService.buildMenuTreeSelect(list));
    }
    
    @ApiOperation(value = "批量删除角色")
    @DeleteMapping("/{roleIds}")
    public ServerResponse<String> delete(
            @ApiParam(value = "要删除的角色ID数组", required = true)
            @PathVariable Integer[] roleIds) {
        return roleService.deleteRoles(roleIds);
    }
    
    @ApiOperation(value = "修改角色")
    @PutMapping("/")
    public ServerResponse<String> updateRole(@RequestBody RoleDto roleDto) {
        roleService.checkData(roleDto);
        roleService.checkRoleDataScope(roleDto.getRoleId());
        
        if (roleDto.getRoleId() == null) {
            throw new CustomException("修改角色'" + roleDto.getRoleName() + "'失败，角色编号不正确");
        }
        
        // 校验角色名称是否唯一
        if (roleService.checkRoleNameUnique(roleDto).equals(Const.NOT_UNIQUE)) {
            throw new CustomException("修改角色'" + roleDto.getRoleName() + "'失败，角色名称已存在");
        }
        
        // 校验角色权限是否唯一
        if (roleService.checkRoleSecurityUnique(roleDto).equals(Const.NOT_UNIQUE)) {
            throw new CustomException("修改角色'" + roleDto.getRoleName() + "'失败，角色权限已存在");
        }
    
        // 校验角色等级是否超过当前用户所拥有的的等级
        if (roleService.checkRoleLevelAllowed(roleDto).equals(Const.UNAUTHORIZED)) {
            throw new CustomException("修改角色'" + roleDto.getRoleName() + "'失败，权限等级大于或等于当前用户权限");
        }
        
        if (roleService.updateRole(roleDto) > 0) {
            // 更新缓存用户权限
            LoginUser loginUser = SecurityUtil.getLoginUser();
            if (loginUser.getUser() != null && !loginUser.getUser().isAdmin()) {
                loginUser.setUser(userService.selectUserByUsername(loginUser.getUsername()));
                jwtTokenUtil.setLoginUser(loginUser);
            }
            
            // 删除缓存中菜单权限值
            if (redisUtil.getObject(Const.MENU_ROLE_KEY + Const.ROLE_SECURITY_PREFIX) != null) {
                redisUtil.deleteObject(Const.MENU_ROLE_KEY + Const.ROLE_SECURITY_PREFIX);
            }
            
            // 查询该角色绑定的用户，删除缓存中的对应用户的菜单数据以及角色数据
            List<User> list = userService.list(new QueryWrapper<User>().eq(User.ROLE_ID, roleDto.getRoleId()));
            list.forEach(user -> {
                String keySuffix = user.getUsername() + "_" + user.getUserId();
                if (redisUtil.getObject(Const.LOGIN_USER_KEY + keySuffix) != null) {
                    redisUtil.deleteObject(Const.LOGIN_USER_KEY + keySuffix);
                }
                if (redisUtil.getObject(Const.MENU_ROLE_KEY + keySuffix) != null) {
                    redisUtil.deleteObject(Const.MENU_ROLE_KEY + keySuffix);
                }
            });
            
            return ServerResponse.createBySuccessMessage(ReturnMessage.UPDATE_SUCCESS);
        }
        
        return ServerResponse.createByErrorMessage("修改角色'" + roleDto.getRoleName() + "'失败，请联系管理员");
    }
    
    @ApiOperation(value = "新增角色")
    @PostMapping("/")
    public ServerResponse<String> add(@RequestBody RoleDto roleDto) {
        
        // 验证数据输入的正确性
        roleService.checkData(roleDto);
        
        // 校验角色名称是否唯一
        if (roleService.checkRoleNameUnique(roleDto).equals(Const.NOT_UNIQUE)) {
            throw new CustomException("新增角色'" + roleDto.getRoleName() + "'失败，角色名称已存在");
        }
        
        // 校验角色权限是否唯一
        if (roleService.checkRoleSecurityUnique(roleDto).equals(Const.NOT_UNIQUE)) {
            throw new CustomException("新增角色'" + roleDto.getRoleName() + "'失败，角色权限已存在");
        }
        
        // 校验角色等级是否超过当前用户所拥有的的等级
        if (roleService.checkRoleLevelAllowed(roleDto).equals(Const.UNAUTHORIZED)) {
            throw new CustomException("新增角色'" + roleDto.getRoleName() + "'失败，权限等级大于或等于当前用户权限");
        }
        
        return roleService.add(roleDto);
    }
    
    @ApiOperation(value = "获取有权管理的角色列表(分页)")
    @GetMapping("/list")
    public ServerResponse<PageResult> getRolesByPage(RoleQueryDto role) {
        return roleService.getRolesByPage(role.getPage(), role.getLimit(), role);
    }
    
    @ApiOperation(value = "根据角色ID获取角色信息")
    @GetMapping("/{roleId}")
    public ServerResponse<RoleVo> getByRoleId(@ApiParam(value = "角色ID", required = true) @PathVariable Integer roleId) {
        roleService.checkRoleDataScope(roleId);
        Role role = roleService.getById(roleId);
        RoleVo roleVo = new RoleVo();
        BeanUtils.copyProperties(role, roleVo);
        String str =
                roleVo.getRoleSecurity().substring(roleVo.getRoleSecurity().indexOf(Const.ROLE_SECURITY_PREFIX) + Const.ROLE_SECURITY_PREFIX.length());
        roleVo.setRoleSecurity(str);
        
        return ServerResponse.createBySuccess(roleVo);
    }
}
